package store

import (
	"codejy/globalfunc"
	"codejy/structdef"
	"codejy/utils"
	"strings"
)

func init() {

}

// key:线程id,value:线程存储
var ThreadStoreMap = utils.NewSyncMap[string, *structdef.ThreadStore]()

// 获取当前线程存储
func GetThreadStore(threadId string) *structdef.ThreadStore {
	if threadStore, ok := ThreadStoreMap.Get(threadId); ok {
		return threadStore
	}
	return nil
}

// 创建线程存储 ,返回线程Id
func CreateThread() (string, *structdef.ThreadStore) {
	threadId := utils.ThreadIdGenerato()
	threadStore := &structdef.ThreadStore{
		VariableStoreMap:                  make(map[string]map[string]structdef.VarDefinition),
		InstanceStore:                     make(map[string]map[string]structdef.VarDefinition),
		TypeDefaultInstanceStore:          make(map[string]map[string]structdef.TypeDefault),
		TypeDefaultInstanceInversionStore: make(map[string]string),
		ExecuteCodeRecordLogMap:           []structdef.RecordLog{},
		ThreadId:                          threadId,
		MapCodeTime:                       make(map[string]map[structdef.LineCodeDefinition]int),
	}
	exist := ThreadStoreMap.IsExist(threadId)
	if exist {
		panic(threadId + "线程存储已经存在")
	}
	ThreadStoreMap.Add(threadId, threadStore)
	return threadId, threadStore
}

// 删除线程存储
func DeleteThreadStore(threadId string) {
	ThreadStoreMap.Delete(threadId)
}

// 复制线程存储返回新线程存储id
func CopyThread(oldThreadStore *structdef.ThreadStore, lineCodes []structdef.LineCodeDefinition, currentPoint int, currentEnv string) (string, *structdef.ThreadStore) {
	//创建新线程存储
	newThreadId, newThreadStore := CreateThread()
	//复制旧线程存储到新线程存储
	AddGlobalEnv(newThreadStore, oldThreadStore.GlobalEnv)
	AddCurrentEnv(newThreadStore, currentEnv)
	AddParentEnv(newThreadStore, currentEnv)
	newThreadStore.CurrentPoint = currentPoint
	newThreadStore.HandleFilePath = oldThreadStore.HandleFilePath
	newThreadStore.BreakFlag = false
	newThreadStore.ContinueFlag = false
	newThreadStore.ReturnFlag = false
	newThreadStore.ThreadStopFlag = false
	newThreadStore.ThreadChan = make(chan string)
	newThreadStore.CurrentInstanceAddress = ""
	newThreadStore.ParentInstanceAddress = ""
	newThreadStore.ExecuteCodeRecordLogMap = []structdef.RecordLog{}
	newThreadStore.MapCodeTime = make(map[string]map[structdef.LineCodeDefinition]int)
	newThreadStore.Codes = lineCodes
	newThreadStore.Code = lineCodes[currentPoint]

	newThreadStore.VariableStoreMap = make(map[string]map[string]structdef.VarDefinition)
	newThreadStore.InstanceStore = make(map[string]map[string]structdef.VarDefinition)
	newThreadStore.TypeDefaultInstanceStore = make(map[string]map[string]structdef.TypeDefault)
	newThreadStore.TypeDefaultInstanceInversionStore = make(map[string]string)
	//将主线程全局作用域的变量复制到新线程存储
	m := oldThreadStore.VariableStoreMap[oldThreadStore.GlobalEnv]
	newThreadStore.VariableStoreMap[newThreadStore.GlobalEnv] = make(map[string]structdef.VarDefinition)
	for k, v := range m {
		newThreadStore.VariableStoreMap[newThreadStore.GlobalEnv][k] = v
		//判断v是否是全局变量和共享变量
		instanceAddress := globalfunc.ExecuteFunc("GetInstanceAddress").(int)
		typeShareInstanceGlobal := globalfunc.ExecuteFunc("GetTypeShareInstanceGlobal").(int)
		if v.VarType == instanceAddress || v.VarType == typeShareInstanceGlobal {
			store, typeName := GetTypeDefaultInstanceInversionStore(oldThreadStore, v.Value)
			//如果不存在新的线程中那么就添加
			//这样做的原因的函数返回值是存储在函数名称的变量中的，那么如果多个不同函数返回的值都是同一个实例地址
			//那么在往新的线程存储里添加时候就会出现此实例已经被注册了
			if !IsInstanceExist(newThreadStore, v.Value) {
				if store { //如果是默认实例
					AddTypeDefaultInstanceStore(newThreadStore, typeName, v.Value, oldThreadStore.TypeDefaultInstanceStore[typeName][v.Value])
					RegisterInstance(newThreadStore, v.Value, oldThreadStore.InstanceStore[v.Value])
				} else { //如果是自定义实例
					RegisterInstance(newThreadStore, v.Value, oldThreadStore.InstanceStore[v.Value])
				}
			}
		}
	}

	return newThreadId, newThreadStore
}

func AddCurrentEnv(threadStore *structdef.ThreadStore, env string) {
	//如果开头不是@scope@那么就添加,如果是表示可能是父作用域传递过来的,那么就不需要重新生成添加
	if !strings.HasPrefix(env, "@scope@") {
		env = utils.ScopeIdGenerato() + "@funcName@" + env
	}
	threadStore.CurrentEnv = env
}

// 添加父作用域
func AddParentEnv(threadStore *structdef.ThreadStore, env string) {
	//如果开头不是@scope@那么就添加,如果是表示可能是父作用域传递过来的,那么就不需要重新生成添加
	if !strings.HasPrefix(env, "@scope@") {
		env = utils.ScopeIdGenerato() + "@funcName@" + env
	}
	threadStore.ParentEnv = env
}
func AddGlobalEnv(threadStore *structdef.ThreadStore, env string) {
	//如果开头不是@scope@那么就添加,如果是表示可能是父作用域传递过来的,那么就不需要重新生成添加
	if !strings.HasPrefix(env, "@scope@") {
		env = utils.ScopeIdGenerato() + "@funcName@" + env
	}
	threadStore.GlobalEnv = env
}

// 获取所有线程id
func GetThreadStores() []*structdef.ThreadStore {
	var stores []*structdef.ThreadStore
	ThreadStoreMap.Range(func(key string, value *structdef.ThreadStore) bool {
		stores = append(stores, value)
		return true
	})
	return stores
}
